home *** CD-ROM | disk | FTP | other *** search
- /* functions for zooming windows and for saving and restoring window positions.
- 94/01/08 aih - moved WinCouldDrag to WindowPositionLib.c
- 93/12/16 aih - added dfltpos field to window structure
- 93/11/27 aih - split from WindowPositionLib.c */
-
- #include <stdlib.h>
- #include <string.h>
- #include "ArchiveLib.h"
- #include "DrawLib.h"
- #include "FileLib.h"
- #include "MathLib.h"
- #include "MemoryLib.h"
- #include "RectangleLib.h"
- #include "ResourceConstantsLib.h"
- #include "ResourceLib.h"
- #include "ResourceTypeLib.h"
- #include "ScreenLib.h"
- #include "WindowLib.h"
-
- /* Version of this library, which is used to determine if window data
- written to a file with a different version of this library can be
- used with the current version. */
- #define WIN_VERSION (3)
-
- /* structure used to save and restore a window's size, position, and zoom
- state */
- typedef struct {
- Boolean zoomed; /* true if in zoomed state */
- Rect bounds; /* window's user and standard states */
- } WindowStateType;
-
- /* get the window's zoom state */
- void WinZoomState(WindowPtr window, WStateData *zoomState)
- {
- require(WinHasZoom(window));
- *zoomState = **(WStateData **) ((WindowPeek) window)->dataHandle;
- }
-
- /* set the window's user and standard states */
- void WinZoomStateSet(WindowPtr window, const WStateData *zoomState)
- {
- require(WinHasZoom(window));
- **(WStateData **) ((WindowPeek) window)->dataHandle = *zoomState;
- }
-
- /* initialize window's user state */
- void WinZoomReset(WindowPtr window)
- {
- WStateData zoomState;
-
- if (WinHasZoom(window)) {
- WinZoomState(window, &zoomState);
- WinContentRect(window, &zoomState.userState);
- WinZoomStateSet(window, &zoomState);
- }
- }
-
- /* true if the window is in the standard state (see IM-IV, p10) */
- static Boolean WinZoomed(WindowPtr window)
- {
- WStateData zoomState;
- Rect contentRect;
- Boolean result = false;
-
- if (WinHasZoom(window)) {
- WinZoomState(window, &zoomState);
- WinContentRect(window, &contentRect);
- result =
- (abs(contentRect.top - zoomState.stdState.top) <= 7 &&
- abs(contentRect.left - zoomState.stdState.left) <= 7 &&
- abs(contentRect.bottom - zoomState.stdState.bottom) <= 7 &&
- abs(contentRect.right - zoomState.stdState.right) <= 7);
- }
- return(result);
- }
-
- /* Prepare to zoom the window by calculating its standard state. This function
- should be called after a mouseDown in the zoom box of the window, but before
- TrackBox is called. This function should also be called just before
- a window's state is restored from a saved file, in case the saved
- state indicates that the window should be zoomed. */
- void WinZoomPrepare(WindowPtr window)
- {
- short width, height; /* window's preferred width and height */
- Rect sizeRect; /* window's minimum and maximum size */
- Rect newRect; /* maximum rectangle of a new window */
- Rect contentRect; /* window's content rectangle */
- WStateData zoomState; /* window's zoom state */
-
- require(WinValid(window));
-
- /* use screen containing greatest portion of window */
- ScreenSet(ScreenContainingWindow(window));
-
- /* adjust width and height to minimum and maximum size of window and
- to maximum size of a window on the current screen */
- WinNewRect(window, &newRect);
- WinSizeRect(window, &sizeRect);
- WinSizePreferred(window, &width, &height);
- check(sizeRect.left <= RectWidth(&newRect));
- check(sizeRect.top <= RectHeight(&newRect));
- width = min(min(max(width, sizeRect.left), sizeRect.right), RectWidth(&newRect));
- height = min(min(max(height, sizeRect.top), sizeRect.bottom), RectHeight(&newRect));
-
- /* set the zoom rectangle's size to the new width and height of the
- window, and use the window's current position if the entire window
- would be visible on the current screen */
- WinZoomState(window, &zoomState);
- WinContentRect(window, &contentRect);
- zoomState.stdState.top = contentRect.top;
- zoomState.stdState.left = contentRect.left;
- zoomState.stdState.bottom = zoomState.stdState.top + height;
- zoomState.stdState.right = zoomState.stdState.left + width;
- if (! RectWithin(&zoomState.stdState, &newRect)) {
- zoomState.stdState.top = newRect.top;
- zoomState.stdState.left = newRect.left;
- zoomState.stdState.bottom = zoomState.stdState.top + height;
- zoomState.stdState.right = zoomState.stdState.left + width;
- }
- WinZoomStateSet(window, &zoomState);
- }
-
- /* zoom the window */
- void WinZoom(WindowPtr window, short part)
- {
- Rect oldPortRect, newPortRect;
- Rect oldContent, newContent;
- GrafPtr port = NULL;
-
- require(WinValid(window));
- GetPort(&port);
- SetPort(window);
- WinPortRect(window, &oldPortRect);
- WinContentRect(window, &oldContent);
- ZoomWindow(window, part, false);
- WinPortRect(window, &newPortRect);
- WinContentRect(window, &newContent);
- if (EqualPt(topLeft(oldContent), topLeft(newContent))) {
- /* window didn't move */
- InvalXorRect(&oldPortRect, &newPortRect);
- if (WinHasGrow(window)) {
- /* invalidate grow region */
- oldPortRect.top = oldPortRect.bottom - 15;
- oldPortRect.left = oldPortRect.right - 15;
- newPortRect.top = newPortRect.bottom - 15;
- newPortRect.left = newPortRect.left - 15;
- EraseRect(&oldPortRect);
- InvalRect(&oldPortRect);
- EraseRect(&newPortRect);
- InvalRect(&newPortRect);
- }
- }
- else {
- /* window moved */
- EraseRect(&newPortRect);
- InvalRect(&newPortRect);
- }
- SetPort(port);
- ensure(WinValid(window));
- }
-
- /*----------------------------------------------------------------------------*/
- /* saving and restoring a window's zoom state */
- /*----------------------------------------------------------------------------*/
-
- /* true if window has been moved or resized */
- static Boolean WinMovedOrResized(WindowPtr window)
- {
- Rect curpos, dfltpos;
-
- dfltpos = WinExtraPtr(window)->dfltpos;
- WinPortRect(window, &curpos);
- RectPortToGlobal(&curpos, window);
- return(! EqualRect(&curpos, &dfltpos));
- }
-
- /* get the window's state */
- static void WinState(WindowPtr window, WindowStateType *state)
- {
- require(WinValid(window));
- memclr(state, sizeof(WindowStateType));
- if (WinMovedOrResized(window))
- WinContentRect(window, &state->bounds);
- state->zoomed = WinZoomed(window);
- }
-
- /* adjust the state so it's in accordance with HIN#6 */
- static void WinStateFix(WindowPtr window, WindowStateType *state)
- {
- RgnHandle invisibleRgn; /* region of rectangle that is invisible */
- WindowStateType dflt; /* window's default state */
- Rect sizeRect; /* window's minimum and maximum size */
- Rect contentRect; /* window's content rectangle */
-
- require(WinValid(window));
-
- /* use default rectangle if current rectangle isn't valid */
- WinSizeRect(window, &sizeRect);
- WinContentRect(window, &contentRect);
- if (! RectValid(&state->bounds) ||
- RectWidth(&state->bounds) < sizeRect.left ||
- RectWidth(&state->bounds) > sizeRect.right ||
- RectHeight(&state->bounds) < sizeRect.top ||
- RectHeight(&state->bounds) > sizeRect.bottom)
- {
- state->bounds = contentRect;
- }
- else if (! WinCouldDrag(window, &state->bounds)) {
-
- /* window can't be dragged so use default position */
- RectMove(&state->bounds, contentRect.left, contentRect.top);
-
- /* use default size if any part of the window would be invisible */
- invisibleRgn = BeginRgn();
- RectRgn(invisibleRgn, &state->bounds);
- DiffRgn(invisibleRgn, GetGrayRgn(), invisibleRgn);
- if (! EmptyRgn(invisibleRgn))
- state->bounds = contentRect;
- EndRgn(invisibleRgn);
- }
- }
-
- /* apply the state to the window */
- static void WinStateApply(WindowPtr window, WindowStateType *state)
- {
- WStateData zoomState;
- Rect oldSize, newSize;
- short dh, dv;
-
- require(WinValid(window));
- if (WinHasZoom(window)) {
- WinZoomPrepare(window);
- WinZoomState(window, &zoomState);
- zoomState.userState = state->bounds;
- if (state->zoomed)
- state->bounds = zoomState.stdState;
- WinZoomStateSet(window, &zoomState);
- }
- WinPortRect(window, &oldSize);
- if (WinHasGrow(window) || WinHasZoom(window)) {
- /* only resize if window's size can change; this guards against
- invalid states and against having changes made to window sizes in
- the resource file being overridden by old preferences files */
- WinSize(window, RectWidth(&state->bounds), RectHeight(&state->bounds));
- }
- WinMove(window, state->bounds.left, state->bounds.top);
- WinPortRect(window, &newSize);
- WinResize(window, RectWidth(&newSize) - RectWidth(&oldSize),
- RectHeight(&newSize) - RectHeight(&oldSize));
- ensure(WinValid(window));
- ensure((WinHasZoom(window) && state->zoomed) ? WinZoomed(window) : true);
- }
-
- /* remember the window's current position as the default position */
- void WinZoomRemember(WindowPtr window)
- {
- Rect pos;
-
- WinPortRect(window, &pos);
- RectPortToGlobal(&pos, window);
- WinExtraPtr(window)->dfltpos = pos;
- }
-
- /* Read the window's position, size, and zoom states from the resource
- with the specified ID in the current resource file. The restored state
- is adjusted to a reasonable size for the window and then applied to
- the window. This function attempts to adhere to the guidelines in the
- HIN and in IM-VI. */
- void WinZoomRead(WindowPtr window, short id)
- {
- WindowStateType state; /* archived state data */
- size_t size; /* size of archived data */
- long version; /* version of archived data */
-
- require(WinValid(window));
- size = sizeof(WindowStateType);
- version = WIN_VERSION;
- ArchiveReadRes(RES_WPOS_TYPE, id, &state, &size, &version);
- if (version != WIN_VERSION || size != sizeof(WindowStateType))
- memclr(&state, sizeof(WindowStateType));
- WinStateFix(window, &state);
- WinStateApply(window, &state);
- WinZoomRemember(window);
- }
-
- /* Write the window's position, size, and zoom states to the resource
- with the specified ID in the current resource file. The window's state
- can later be restored with WinZoomRestore. */
- void WinZoomWrite(WindowPtr window, short id)
- {
- WindowStateType state;
-
- require(WinValid(window));
- if (WinMovedOrResized(window)) {
- WinState(window, &state);
- ArchiveWriteRes(RES_WPOS_TYPE, id, &state, sizeof(WindowStateType), WIN_VERSION);
- }
- }
-
- /* Read the window's state from the resource with the specified
- ID in the specified file's resource fork. */
- void WinZoomRestore(WindowPtr window, FileType *fp, short id)
- {
- volatile FileRefType ref = FILE_CLOSED;
-
- TRY {
- if (ResFileExists(fp)) {
- ref = ResFileOpen(fp, fsRdPerm);
- if (ResExists1(RES_WPOS_TYPE, id))
- WinZoomRead(window, id);
- }
- WinZoomRemember(window);
- } CLEANUP {
- ResFileClose(ref);
- } ENDTRY;
- }
-
- /* Save the window's current state if it differs from the default state. The
- state is written to the resource fork of the specified file, and the
- file's modification date is unchanged. */
- void WinZoomSave(WindowPtr window, FileType *fp, short id)
- {
- CInfoPBRec pb;
- volatile FileRefType ref = FILE_CLOSED;
-
- TRY {
- if (WinMovedOrResized(window)) {
- FileCatalog(fp, &pb);
- if (! ResFileExists(fp))
- ResFileCreate(fp);
- ref = ResFileOpen(fp, fsWrPerm);
- WinZoomWrite(window, id);
- ResFileClose(ref);
- ref = FILE_CLOSED;
- FileCatalogSet(fp, &pb);
- }
- } CATCH {
- ResFileClose(ref);
- } ENDTRY;
- }
-